﻿using System;
using System.Xml;
using System.Drawing;
using System.Windows.Forms;

namespace AeroWeather
{
    public static class WeatherAPI
    {
        private enum Conditions
        {
            TORNADO,
            TROPICAL_STORM,
            HURRICANE,
            SEVERE_THUNDERSTORMS,
            THUNDERSTORMS,
            MIXED_RAIN_AND_SNOW,
            MIXED_RAIN_AND_SLEET,
            MIXED_SNOW_AND_SLEET,
            FREEZING_DRIZZLE,
            DRIZZLE,
            FREEZING_RAIN,
            SHOWERS,
            SHOWERS2,
            SNOW_FLURRIES,
            LIGHT_SNOW_SHOWERS,
            BLOWING_SNOW,
            SNOW,
            HAIL,
            SLEET,
            DUST,
            FOGGY,
            HAZE,
            SMOKY,
            BLUSTERY,
            WINDY,
            COLD,
            CLOUDY,
            MOSTLY_CLOUDY_NIGHT,
            MOSTLY_CLOUDY_DAY,
            PARTLY_CLOUDY_NIGHT,
            PARTLY_CLOUDY_DAY,
            CLEAR_NIGHT,
            SUNNY,
            FAIR_NIGHT,
            FAIR_DAY,
            MIXED_RAIN_AND_HAIL,
            HOT,
            ISOLATED_THUNDERSTORMS,
            SCATTERED_THUNDERSTORMS,
            SCATTERED_THUNDERSTORMS2,
            SCATTERED_SHOWERS,
            HEAVY_SNOW,
            SCATTERED_SNOW_SHOWERS,
            HEAVY_SNOW2,
            PARTLY_CLOUDY,
            THUNDERSHOWERS,
            SNOW_SHOWERS,
            ISOLATED_THUNDERSHOWERS
        };

        private static XmlDocument RetrieveRSS(string zip)
        {
            XmlDocument rssDoc = new XmlDocument();
            rssDoc.Load(new XmlTextReader(Properties.Resources.WeatherAPIBaseURL + zip));
            return rssDoc;
        }

        public static bool isValidZip(string zip)
        {
            XmlDocument rssDoc;
            try
            {
                rssDoc = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to retrieve weather information. If this message persists, close the application until a valid internet connection is established.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            XmlNodeList title = rssDoc.GetElementsByTagName("title");
            if (title[0].InnerText.IndexOf("Error") > -1)
            {
                return false;
            }

            return true;
        }

        public static int GetCurrentTemperature(string zip)
        {
            XmlDocument rss;
            try
            {
                rss = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to retrieve weather information. Your color may not be set properly. If this message persists, close the application until a valid internet connection is established.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return 0;
            }
            XmlNodeList items = rss.GetElementsByTagName("yweather:condition");

            // Anytime we get by tag name it will be unique, so assume 1 result.
            XmlNode weatherInfo = items[0];

            XmlNode temp = weatherInfo.Attributes.GetNamedItem("temp");
          
            return Int32.Parse(temp.InnerText);
        }

        public static DateTime GetSunrise(string zip)
        {
            XmlDocument rss;
            try
            {
                rss = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to retrieve weather information. Your color may not be set properly. If this message persists, close the application until a valid internet connection is established.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return DateTime.Now;
            }
            XmlNodeList items = rss.GetElementsByTagName("yweather:astronomy");

            // Anytime we get by tag name it will be unique, so assume 1 result.
            XmlNode weatherInfo = items[0];

            XmlNode temp = weatherInfo.Attributes.GetNamedItem("sunrise");

            return DateTime.Parse(temp.InnerText);
        }

        public static DateTime GetSunset(string zip)
        {
            XmlDocument rss;
            try
            {
                rss = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to retrieve weather information. Your color may not be set properly. If this message persists, close the application until a valid internet connection is established.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return DateTime.Now;
            }
            XmlNodeList items = rss.GetElementsByTagName("yweather:astronomy");

            // Anytime we get by tag name it will be unique, so assume 1 result.
            XmlNode weatherInfo = items[0];

            XmlNode temp = weatherInfo.Attributes.GetNamedItem("sunset");

            return DateTime.Parse(temp.InnerText);
        }

        public static string GetCityStateString(string zip)
        {
            XmlDocument rss;
            try
            {
                rss = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                return "";
            }
            XmlNodeList items = rss.GetElementsByTagName("yweather:location");
            XmlNode weatherInfo = items[0];

            XmlNode city = weatherInfo.Attributes.GetNamedItem("city");
            XmlNode state = weatherInfo.Attributes.GetNamedItem("region");
            return city.InnerText + ", " + state.InnerText;
        }

        public static int GetCurrentConditions(string zip)
        {
            XmlDocument rss;
            try
            {
                rss = RetrieveRSS(zip);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to retrieve weather information. Your color may not be set properly. If this message persists, close the application until a valid internet connection is established.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return (int)Conditions.CLOUDY;
            }
            XmlNodeList items = rss.GetElementsByTagName("yweather:condition");

            XmlNode weatherInfo = items[0];

            XmlNode condition = weatherInfo.Attributes.GetNamedItem("code");

            return Int32.Parse(condition.InnerText);
        }

        public static Color GetColorFromConditions(int condition)
        {
            return GetColorFromConditions((Conditions)condition);
        }

        private static Color GetColorFromConditions(Conditions condition)
        {
            // Ugly list of stuff.
            switch (condition)
            {
                case Conditions.TORNADO:
                case Conditions.TROPICAL_STORM:
                case Conditions.HURRICANE:
                case Conditions.SEVERE_THUNDERSTORMS:
                case Conditions.THUNDERSTORMS:
                    return Color.Purple;
                case Conditions.MIXED_RAIN_AND_SNOW:
                case Conditions.MIXED_RAIN_AND_SLEET:
                case Conditions.MIXED_SNOW_AND_SLEET:
                case Conditions.FREEZING_DRIZZLE:
                    return Color.White;
                case Conditions.DRIZZLE:
                    return Color.LightBlue;
                case Conditions.FREEZING_RAIN:
                    return Color.White;
                case Conditions.SHOWERS:
                case Conditions.SHOWERS2:
                    return Color.LightBlue;
                case Conditions.SNOW_FLURRIES:
                case Conditions.LIGHT_SNOW_SHOWERS:
                case Conditions.BLOWING_SNOW:
                case Conditions.SNOW:
                    return Color.White;
                case Conditions.HAIL:
                case Conditions.SLEET:
                case Conditions.DUST:
                case Conditions.FOGGY:
                case Conditions.HAZE:
                case Conditions.SMOKY:
                case Conditions.BLUSTERY:
                case Conditions.WINDY:
                case Conditions.COLD:
                case Conditions.CLOUDY:
                    return Color.Gray;
                case Conditions.MOSTLY_CLOUDY_NIGHT:
                case Conditions.MOSTLY_CLOUDY_DAY:
                    return Color.Gray;
                case Conditions.PARTLY_CLOUDY_NIGHT:
                case Conditions.PARTLY_CLOUDY_DAY:
                    return Color.FromArgb(183, 201, 223);
                case Conditions.CLEAR_NIGHT:
                    return Color.Black;
                case Conditions.SUNNY:
                    return Color.Blue;
                case Conditions.FAIR_NIGHT:
                case Conditions.FAIR_DAY:
                    return Color.LightBlue;
                case Conditions.MIXED_RAIN_AND_HAIL:
                    return Color.Gray;
                case Conditions.HOT:
                    return Color.Orange;
                case Conditions.ISOLATED_THUNDERSTORMS:
                case Conditions.SCATTERED_THUNDERSTORMS:
                case Conditions.SCATTERED_THUNDERSTORMS2:
                    return Color.Purple;
                case Conditions.SCATTERED_SHOWERS:
                    return Color.Gray;
                case Conditions.HEAVY_SNOW:
                    return Color.White;
                case Conditions.SCATTERED_SNOW_SHOWERS:
                    return Color.Gray;
                case Conditions.HEAVY_SNOW2:
                    return Color.White;
                case Conditions.PARTLY_CLOUDY:
                    return Color.LightBlue;
                case Conditions.THUNDERSHOWERS:
                    return Color.Blue;
                case Conditions.SNOW_SHOWERS:
                    return Color.DarkGray;
                case Conditions.ISOLATED_THUNDERSHOWERS:
                    return Color.LightGray;
                default:
                    return Color.LightBlue;
            }
        }

        public static Color GetColorFromTemp(int lowerBound, int upperBound, int temperature)
        {
            int interval = (upperBound - lowerBound) / 5;
            if (temperature > upperBound)
            {
                return (Color.Red);
            }
            else if (temperature > (4 * interval) + lowerBound)
            {
                int res = ((temperature - (int)(4 * interval) - lowerBound) * 255) / interval;
                return (Color.FromArgb(255, 255 - res, 0));
            }
            else if (temperature > (3 * interval) + lowerBound)
            {
                int res = ((temperature - (3 * interval) - lowerBound) * 255) / interval;
                return (Color.FromArgb(res, 255, 0));
            }
            else if (temperature > (2 * interval) + lowerBound)
            {
                int res = ((temperature - (2 * interval) - lowerBound) * 255) / interval;
                return (Color.FromArgb(0, 255, 255 - res));
            }
            else if (temperature > interval + lowerBound)
            {
                int res = ((temperature - interval - lowerBound) * 255) / interval;
                return (Color.FromArgb(0, res, 255));
            }
            else if (temperature > lowerBound)
            {
                int res = ((temperature - lowerBound) * 255) / interval;
                return (Color.FromArgb(128 - (res / 2), 0, 255));
            }
            else
            {
                return (Color.FromArgb(128, 0, 255));
            }
        }
    }
}